<?php
declare (strict_types = 1);
// +----------------------------------------------------------------------
// | 尘墨成 [ DustInk Package ]
// +----------------------------------------------------------------------
// | Copyright (c) 2021~2021 https://www.dustink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 尘墨成 <dustink@sina.com>
// +----------------------------------------------------------------------
// | 创建于2021年09月19日 06:05
// +----------------------------------------------------------------------
// | 日期工具类
// +----------------------------------------------------------------------

namespace DustInk\Tools;

class Date
{
    /**
     * 获取今日起始时间
     * Get the start time of today
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getTodayStart(bool $isTimeStamp = false)
    {
        $date = date('Y-m-d 00:00:00', time());
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取今日结束时间
     * Get the end time of today
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getTodayEnd(bool $isTimeStamp = false)
    {
        $date = date('Y-m-d 23:59:59', time());
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取昨日起始时间
     * Get the start time of yesterday
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getYesterdayStart(bool $isTimeStamp = false)
    {
        $date = date("Y-m-d 00:00:00", strtotime("-1 day"));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取昨日结束时间
     * Get the end time of yesterday
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getYesterdayEnd(bool $isTimeStamp = false)
    {
        $date = date("Y-m-d 23:59:59", strtotime("-1 day"));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取上周起始时间
     * Get the start time of last week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastWeekStart(bool $isTimeStamp = false)
    {
        $date = date("Y-m-d H:i:s", mktime(0, 0, 0, (int)date("m"), (int)date("d") - (int)date("w") + 1 - 7, (int)date("Y")));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取上周结束时间
     * Get the end time of last week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastWeekEnd(bool $isTimeStamp = false)
    {
        $date = date("Y-m-d H:i:s", mktime(23, 59, 59, (int)date("m"), (int)date("d") - (int)date("w") + 7 - 7, (int)date("Y")));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取本周起始时间
     * Get the start time of the week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisWeekStart(bool $isTimeStamp = false)
    {
        $date = date("Y-m-d H:i:s", mktime(0, 0, 0, (int)date("m"), (int)date("d") - (int)date("w") + 1, (int)date("Y")));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取本周结束时间
     * Get the end time of the week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisWeekEnd(bool $isTimeStamp = false)
    {
        $date = date("Y-m-d H:i:s", mktime(23, 59, 59, (int)date("m"), (int)date("d") - (int)date("w") + 7, (int)date("Y")));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取上月起始时间
     * Get start time of last month
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastMonthStart(bool $isTimeStamp = false)
    {
        $date = date('Y-m-d 00:00:00', strtotime(date('Y-m-01') . ' -1 month'));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取上月结束时间
     * Get the end time of last month
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastMonthEnd(bool $isTimeStamp = false)
    {
        $date = date('Y-m-d 23:59:59', strtotime(date('Y-m-01') . ' -1 day'));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取本月起始时间
     * Get the start time of this month
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisMonthStart(bool $isTimeStamp = false)
    {
        $date = date("Y-m-01 00:00:00");
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取本月结束时间
     * Get the end time of this month
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisMonthEnd(bool $isTimeStamp = false)
    {
        $date = date("Y-m-t 23:59:59");
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取本季度起始时间
     * Get the start time of this quarter
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisQuarterStart(bool $isTimeStamp = false)
    {
        $season = ceil((date('n')) / 3);
        $date = date('Y-m-d H:i:s', mktime(0, 0, 0, (int)$season * 3 - 3 + 1, 1, (int)date('Y')));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取本季度结束时间
     * Get the end time of this quarter
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisQuarterEnd(bool $isTimeStamp = false)
    {
        $season = ceil((date('n')) / 3);
        $date = date('Y-m-d H:i:s', mktime(23, 59, 59, (int)$season * 3, (int)date('t', mktime(0, 0, 0, (int)$season * 3, 1, (int)date("Y"))), (int)date('Y')));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取上季度起始时间
     * Get the start time of last quarter
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastQuarterStart(bool $isTimeStamp = false)
    {
        $season = ceil((date('n')) / 3) - 1;
        $date = date('Y-m-d H:i:s', mktime(0, 0, 0, (int)$season * 3 - 3 + 1, 1, (int)date('Y')));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取上季度结束时间
     * Get the last quarter end time
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastQuarterEnd(bool $isTimeStamp = false)
    {
        $season = ceil((date('n')) / 3) - 1;
        $date = date('Y-m-d H:i:s', mktime(23, 59, 59, (int)$season * 3, (int)date('t', mktime(0, 0, 0, (int)$season * 3, 1, (int)date("Y"))), (int)date('Y')));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取去年起始时间
     * Get the start time of last year
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastYearStart(bool $isTimeStamp = false)
    {
        $date = date("Y-01-01 00:00:00", strtotime('-1 year'));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取去年结束时间
     * Get the end time of last year
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getLastYearEnd(bool $isTimeStamp = false)
    {
        $date = date("Y-12-31 23:59:59", strtotime('-1 year'));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取今年起始时间
     * Get the start time of this year
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisYearStart(bool $isTimeStamp = false)
    {
        $date = date("Y-01-01 00:00:00");
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取今年结束时间
     * Get the end time of this year
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getThisYearEnd(bool $isTimeStamp = false)
    {
        $date = date("Y-12-31 23:59:59");
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取某年某季度开始时间
     * Get the start time of a quarter in a year
     * @param int $year
     * @param int $quarter
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getQuarterStart(int $year, int $quarter = 1, bool $isTimeStamp = false)
    {
        $year = $year ?: date('Y', time());
        switch ($quarter) {
            case 1:
                $date = $year . '-01-01 00:00:00';
                break;
            case 2:
                $date = $year . '-04-01 00:00:00';
                break;
            case 3:
                $date = $year . '-07-01 00:00:00';
                break;
            default:
                $date = $year . '-10-01 00:00:00';
                break;
        }
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取某年某季度结束时间
     * Get the end time of a quarter in a year
     * @param int $year
     * @param int $quarter
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getQuarterEnd(int $year, int $quarter = 1, bool $isTimeStamp = false)
    {
        $year = $year ?: date('Y', time());
        switch ($quarter) {
            case 1:
                $date = $year . '-03-31 23:59:59';
                break;
            case 2:
                $date = $year . '-06-30 23:59:59';
                break;
            case 3:
                $date = $year . '-09-30 23:59:59';
                break;
            default:
                $date = $year . '-12-31 23:59:59';
                break;
        }
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取某年某周开始时间
     * Get the start time of a week in a year
     * @param int $year
     * @param int $week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getWeekStart(int $year, int $week = 1, bool $isTimeStamp = false)
    {
        $year = $year ?: date('Y', time());
        $yearStart = mktime(0, 0, 0, 1, 1, $year);
        // 判断第一天是否为第一周的开始
        if (intval(date('W', $yearStart)) === 1) {
            //把第一天做为第一周的开始
            $start = $yearStart;
        } else {
            $week++;
            //把第一个周一作为开始
            $start = strtotime('+1 monday', $yearStart);
        }
        // 第几周的开始时间
        if ($week === 1) {
            $date = date('Y-m-d 00:00:00', strtotime('+1 monday', $start));
        } else {
            $date = date('Y-m-d 00:00:00', strtotime('+' . ($week - 0) . ' monday', $start));
        }
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取某年某周结束时间
     * Get the end time of a week in a year
     * @param int $year
     * @param int $week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getWeekEnd(int $year, int $week = 1, bool $isTimeStamp = false)
    {
        $date = date('Y-m-d 23:59:59', strtotime('+1 sunday', self::getWeekStart($year, $week, true)));
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取某年某月某周开始时间
     * Get the start time of a week in a month in a year
     * @param int $year
     * @param int $month
     * @param int $week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getMonthWeekStart(int $year, int $month, int $week = 1, bool $isTimeStamp = false)
    {
        $year = $year ?: date('Y', time());
        $month = $month ?: date('m', time());
        $monthStart = mktime(0, 0, 0, $month, 1, $year);
        // 判断月第一天是否为第一周的开始
        if (intval(date('W', $monthStart)) === 1) {
            //把月第一天做为月第一周的开始
            $start = $monthStart;
        } else {
            $week++;
            //把第一个周一作为开始
            $start = strtotime('+1 monday', $monthStart);
        }
        // 第几周的开始时间
        if ($week === 1) {
            $date = date('Y-m-d 00:00:00', $start);
        } else {
            $date = date('Y-m-d 00:00:00', strtotime('+' . ($week - 0) . ' monday', $start));
        }
        return $isTimeStamp ? strtotime($date) : $date;
    }

    /**
     * 获取某年某月某周结束时间
     * Get the end time of a week in a month in a year
     * @param int $year
     * @param int $month
     * @param int $week
     * @param bool $isTimeStamp
     * @return false|int|string
     */
    static public function getMonthWeekEnd(int $year, int $month, int $week = 1, bool $isTimeStamp = false)
    {
        $date = date('Y-m-d 23:59:59', strtotime('+1 sunday', self::getMonthWeekStart($year, $month, $week)));
        return $isTimeStamp ? strtotime($date) : $date;
    }
}